package view;
import java.awt.*;
import java.awt.event.*;

import javax.swing.*;

import model.Field;
import model.FieldStats;
import controller.SaveLoad;
import controller.Settings;
import controller.Simulator;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * A graphical view of the simulation grid.
 * The view displays a colored rectangle for each location 
 * representing its contents. It uses a default background color.
 * Colors for each type of species can be defined using the
 * setColor method.
 * 
 * @author David J. Barnes and Michael K��lling
 * @version 2011.07.31
 */
@SuppressWarnings("serial")
public class SimulatorView extends JFrame
{
    // Colors used for empty locations.
    private static final Color EMPTY_COLOR = Color.white;

    // Color used for objects that have no defined color.
    private static final Color UNKNOWN_COLOR = Color.gray;

    private final String STEP_PREFIX = "Step: ";
    private final String POPULATION_PREFIX = "Population: ";
    private JLabel stepLabel, population;
    private final Simulator simulator;
    private FieldView fieldView;
    private JMenuBar menuBar;
    private JMenu menu1;
    private JMenu menu2;
    private JMenu help;
    
    
    private JPanel mainscreen;
    private JViewport settings;
    private JTabbedPane tabbedPane;
    private StatisticView statistic;
    // A map for storing colors for participants in the simulation
    private Map<Class, Color> colors;
    // A statistics object computing and storing simulation information
    private FieldStats stats;
    /**
     * Create a view of the given width and height.
     * @param height The simulation's height.
     * @param width  The simulation's width.
     */
    public SimulatorView(int height, int width, final Simulator simulator)
    {
    	//Make a new JFrame
    	this.simulator = simulator;
    	setTitle("Fox and Rabbit Simulation");
    	colors = new LinkedHashMap<Class, Color>();
    	stats = new FieldStats(simulator);
    	stepLabel = new JLabel(STEP_PREFIX, JLabel.CENTER);
        population = new JLabel(POPULATION_PREFIX, JLabel.CENTER);
        fieldView = new FieldView(height, width);
        JMenu menu = new JMenu();
        
    	
    	//Make the tabs & add icons
    	ImageIcon settingsicon = new ImageIcon("res/settings.png");
    	ImageIcon starticon = new ImageIcon("res/play.png");
    	ImageIcon statsicon = new ImageIcon("res/stats.png");
		tabbedPane = new JTabbedPane();
		
		//Add the buttons
		JButton button1 = new JButton("Step 1");
		button1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {

				simulator.simulateOneStep();

			}
		});
		JButton button2 = new JButton("Step 100");
		button2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				
				simulator.simulate(100);

			}
		});
		
		//Add the main screen
		mainscreen = new JPanel();
		JPanel buttons = new JPanel();
		buttons.add(button1);
		buttons.add(button2);
		mainscreen.add(fieldView, BorderLayout.EAST);
		mainscreen.add(buttons, BorderLayout.WEST);
		
		
		
		//Make the tabs
		statistic = new StatisticView(stats);
		JScrollPane scroll = new JScrollPane();
		settings = new Settings();
		scroll.setViewport(settings);
		tabbedPane.setTabPlacement(JTabbedPane.NORTH);
		tabbedPane.addTab("Foxes and Rabbits", starticon, mainscreen);
		tabbedPane.addTab("Settings", settingsicon, scroll);
		tabbedPane.addTab("Stats", statsicon, statistic);
		

		
		
		add(tabbedPane);
		setVisible(true);
		setSize(900, 650);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
		

        menuBar = new JMenuBar();
        
		menu1 = new JMenu("File");
		menu1.add(
				new AbstractAction("Reset"){
					public void actionPerformed(ActionEvent event){
						simulator.reset();
					}
				}
			);
		menu1.add(
				new AbstractAction("Save"){
					public void actionPerformed(ActionEvent event){
						SaveLoad.save("def", simulator);
					}
				}
			);
		menu1.add(
				new AbstractAction("Load"){
					public void actionPerformed(ActionEvent event){
						SaveLoad.load("def", simulator, simulator.getActors());
					}
				}
			);
		menu2 = new JMenu("Options");
		help = new JMenu("Help");
		
		menuBar.add(menu1);
		menuBar.add(menu2);
		menuBar.add(help);
        
		setJMenuBar(menuBar);
    	
    	/*this.simulator = simulator;
        stats = new FieldStats();
        colors = new LinkedHashMap<Class, Color>();

        setTitle("Fox and Rabbit Simulation");
        stepLabel = new JLabel(STEP_PREFIX, JLabel.CENTER);
        population = new JLabel(POPULATION_PREFIX, JLabel.CENTER);
        
        setLocation(100, 50);
        
        
        fieldView = new FieldView(height, width);
        menu.add(fieldView);
        
		
		JButton button1 = new JButton("Step 1");
		button1.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {

				simulator.simulateOneStep();

			}
		});
		JButton button2 = new JButton("Step 100");
		button2.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {

				simulator.simulate(100);

			}
		});
		JLabel version = new JLabel("Version 0.0");
		
		JPanel view = new JPanel();

        view.add(stepLabel, BorderLayout.NORTH);
        view.add(fieldView, BorderLayout.CENTER);
        view.add(population, BorderLayout.SOUTH);

        Container contents = getContentPane();
        
        contents.setLayout(null);
        
        //contents.add(view);
        contents.add(button1);
        contents.add(button2);
        contents.add(version);

        button1.setBounds(30, 40, 100, 30);
        button2.setBounds(30, 80, 100, 30);
        view.setBounds(200, 30, 600, 600);
        version.setBounds(30, 550, 100, 30);
        
        pack();
        setVisible(true);
        setSize(900, 660);
        setDefaultCloseOperation(EXIT_ON_CLOSE);*/
    }
    
    /**
     * Define a color to be used for a given class of animal.
     * @param animalClass The animal's Class object.
     * @param color The color to be used for the given class.
     */
    public void setColor(Class animalClass, Color color)
    {
        colors.put(animalClass, color);
    }

    /**
     * @return The color to be used for a given class of animal.
     */
    private Color getColor(Class animalClass)
    {
        Color col = colors.get(animalClass);
        if(col == null) {
            // no color defined for this class
            return UNKNOWN_COLOR;
        }
        else {
            return col;
        }
    }

    /**
     * Show the current status of the field.
     * @param step Which iteration step it is.
     * @param field The field whose status is to be displayed.
     */
    public void showStatus(int step, Field field)
    {
        if(!isVisible()) {
            setVisible(true);
        }
            
        stepLabel.setText(STEP_PREFIX + step);
        stats.reset();
        
        fieldView.preparePaint();

        for(int row = 0; row < field.getDepth(); row++) {
            for(int col = 0; col < field.getWidth(); col++) {
                Object animal = field.getObjectAt(row, col);
                if(animal != null) {
                    stats.incrementCount(animal.getClass());
                    fieldView.drawMark(col, row, getColor(animal.getClass()));
                }
                else {
                	Object fieldModifier = field.getModifierAt(row, col);
                	if(fieldModifier != null){
                		fieldView.drawMark(col, row, getColor(fieldModifier.getClass()));
                	} else {
                    fieldView.drawMark(col, row, EMPTY_COLOR);
                	}
                }
            }
        }
        stats.countFinished();      
        population.setText(POPULATION_PREFIX + stats.getAnimalCount());
        fieldView.repaint();
    }

    /**
     * Determine whether the simulation should continue to run.
     * @return true If there is more than one species alive.
     */
    public boolean isViable(Field field)
    {
        return stats.isViable(field);
    }
    
    /**
     * Provide a graphical view of a rectangular field. This is 
     * a nested class (a class defined inside a class) which
     * defines a custom component for the user interface. This
     * component displays the field.
     * This is rather advanced GUI stuff - you can ignore this 
     * for your project if you like.
     */
    
    private class FieldView extends JPanel
    {
        private final int GRID_VIEW_SCALING_FACTOR = 6;

        private int gridWidth, gridHeight;
        private int xScale, yScale;
        Dimension size;
        private Graphics g;
        private Image fieldImage;

        /**
         * Create a new FieldView component.
         */
        public FieldView(int height, int width)
        {
            gridHeight = height;
            gridWidth = width;
            size = new Dimension(0, 0);
        }

        /**
         * Tell the GUI manager how big we would like to be.
         */
        public Dimension getPreferredSize()
        {
            return new Dimension(gridWidth * GRID_VIEW_SCALING_FACTOR,
                                 gridHeight * GRID_VIEW_SCALING_FACTOR);
        }

        /**
         * Prepare for a new round of painting. Since the component
         * may be resized, compute the scaling factor again.
         */
        public void preparePaint()
        {
            if(! size.equals(getSize())) {  // if the size has changed...
                size = getSize();
                fieldImage = fieldView.createImage(size.width, size.height);
                g = fieldImage.getGraphics();

                xScale = size.width / gridWidth;
                if(xScale < 1) {
                    xScale = GRID_VIEW_SCALING_FACTOR;
                }
                yScale = size.height / gridHeight;
                if(yScale < 1) {
                    yScale = GRID_VIEW_SCALING_FACTOR;
                }
            }
        }
        
        /**
         * Paint on grid location on this field in a given color.
         */
        
        public void drawMark(int x, int y, Color color)
        {
            g.setColor(color);
            g.fillRect(x * xScale, y * yScale, xScale-1, yScale-1);
        }

        /**
         * The field view component needs to be redisplayed. Copy the
         * internal image to screen.
         */
        
        public void paintComponent(Graphics g)
        {
            if(fieldImage != null) {
                Dimension currentSize = getSize();
                if(size.equals(currentSize)) {
                    g.drawImage(fieldImage, 0, 0, null);
                }
                else {
                    // Rescale the previous image.
                    g.drawImage(fieldImage, 0, 0, currentSize.width, currentSize.height, null);
                }
            }
        }
    }
}
